/**
 * byte_buffer 简单的字节缓冲区
 * 张勇 41204@qq.com
 */
#pragma once

#include <stdint.h>
#include <string.h>
#include "std_err.h"
#include "unios.h"

/// @brief 简单的字节缓冲区
/// @attention 不支持并发操作
typedef struct {
	uint8_t* data;   	///< 数据存储空间
	size_t size;     	///< 缓冲区尺寸
	size_t dlen;     	///< 当前数据长度
	unios_ms_t timestamp;///< 最后一个数据的时间戳(ms)
} byte_buffer_t;


#ifdef __cplusplus
extern "C" {
#endif

/// 清除缓冲区数据
static inline void byte_buffer_clear(byte_buffer_t* buf) { buf->dlen = 0; buf->timestamp = 0; }
/// 清除缓冲区数据，并初始化为 0
static inline void byte_buffer_zero(byte_buffer_t* buf) { byte_buffer_clear(buf); memset(buf->data, 0, buf->size); }
/// 缓冲区剩余空间长度
static inline size_t byte_buffer_free(byte_buffer_t* buf) { return (buf->size-1) - buf->dlen; }
/// 把缓冲中的数据当作字符串返回
static inline char* byte_buffer_gets(byte_buffer_t* buf) { buf->data[buf->dlen] = '\0'; return (char*)buf->data; }
/// 缓冲区数据长度强制增加
static inline void byte_buffer_inc(byte_buffer_t* buf, size_t size) { buf->dlen += (byte_buffer_free(buf) >= size) ? size : 0; }
/// 丢掉尾部 n bytes 数据
static inline void byte_buffer_cut(byte_buffer_t* buf, size_t nbytes) { buf->dlen = (buf->dlen > nbytes) ? (buf->dlen - nbytes) : 0; }
/// 数据的寿命(最后一个字节已经进来多长时间了，ms)
unios_ms_t byte_buffer_age(byte_buffer_t* buf);
/// 左移 n bytes，丢掉头部 n bytes 数据
void byte_buffer_lshift(byte_buffer_t* buf, size_t nbytes);
/// 放入一个字节
std_err_t byte_buffer_putc(byte_buffer_t* buf, char ch);
/// 放入一块数据
std_err_t byte_buffer_put(byte_buffer_t* buf, size_t len, const uint8_t* data);

#ifdef __cplusplus
}
#endif
